﻿local UnitName, SendChatMessage = UnitName, SendChatMessage

local frame = CreateFrame("Frame",  nil, UIParent)

local countdown = 5.0
local remainingCount = 5.0
local timeSinceLastUpdate = 0.0

local tracking = false
local test = false

local version = "RadenUnstableVita - 1.6.2.2";
local checkVersionTime = 3.0;
local checkVersionElapsed = 0.0;

local raid = {};
local raidCircle = {};
local raidCircleStartPerson = nil;
local raidCircleLastPerson = nil;
local raidCircleCount = 0;
local raidCircleTester = nil;

local vitaSensitive = 138372;

local function HasVitaSensitive (player)
	return UnitDebuff (player, GetSpellInfo (vitaSensitive)) ~= nil;
end

local COVER_COLOR = {};
COVER_COLOR["黃"] = "紫色";
COVER_COLOR["紫"] = "黃色";

local function update_tracking()
	local should_track = (GetMapInfo() == "ThunderKingRaid")
	if should_track ~= tracking then
		if tracking then
			frame:UnregisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
		else
			frame:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
			-- corrected by dh3014. 1: 10N 2: 25N 3: 10H 4: 25H
			if GetRaidDifficultyID() % 2 == 1 then
				--is 10man
				countdown = 12.0
			else
				--is 25man
				countdown = 5.0
			end
		end
		tracking = should_track
	end
end

local function endCountdown()
	frame:SetScript("OnUpdate", nil)
end

local whisperTarget;

local function countdownUpdate(self, elapsed)
	timeSinceLastUpdate = timeSinceLastUpdate + elapsed
	if (timeSinceLastUpdate >= 1.0) then
		timeSinceLastUpdate = 0.0
		-- send message 

		if whisperTarget ~= nil and whisperTarget ~= "" then
			SendChatMessage(remainingCount, "WHISPER", nil, whisperTarget);
			SendChatMessage(remainingCount , "SAY");
		end

		-- not saying countdown for now
		-- SendChatMessage(remainingCount, "SAY")
		
		remainingCount = remainingCount - 1
		if (remainingCount <= -1) then
			local player = UnitName("player")
			SendChatMessage("--"..player.." 電已傳快回中間--" , "SAY")
			PlaySoundFile ("Interface\\Addons\\RadenUnstableVita\\sounds\\ex_mop_kjzc.mp3", "Master");
			endCountdown();
			
			if raidCircleTester ~= nil then
				SendAddonMessage("RUVcheckCircle", "responseTest " .. NextTarget .. " " .. PrevTarget, "WHISPER", raidCircleTester);
				raidCircleTester = nil;
			end
		end
	end

end

local function startCountdown()
	local player = UnitName("player")
	remainingCount = countdown		
	
	whisperTarget = NextTarget;
	if HasVitaSensitive (NextTarget) then
		SendChatMessage (player .. " " .. countdown .. "秒後傳電  但" .. NextTarget .. "身上已有生命敏感", "SAY");
		if Coverage ~= nil and Coverage ~= "" and Coverage ~= "0" then
			SendChatMessage (Coverage .. " 補位", "SAY");
			SendChatMessage ("快去" .. COVER_COLOR[Color] .. "補位", "WHISPER", nil, Coverage);
			whisperTarget = Coverage;
		end
	else
		timeSinceLastUpdate = 1.0 -- for initial message at 0 second
		if NextTarget ~= nil and NextTarget ~= "" then
			SendChatMessage(player.." "..countdown.."秒後傳電 下一個: "..NextTarget, "SAY")
		else
			SendChatMessage(player.." "..countdown.."秒後傳電" , "SAY")
		end
	end
	frame:SetScript("OnUpdate", countdownUpdate)
end

local function CheckVersionResult(self, elapsed)
	checkVersionElapsed = checkVersionElapsed + elapsed;
	if checkVersionElapsed >= checkVersionTime then
		for n, v in pairs(raid) do
			if v ~= version then
				DEFAULT_CHAT_FRAME:AddMessage("  " .. n .. ": " .. v);
			end
		end
		DEFAULT_CHAT_FRAME:AddMessage("RadenUnstableVita - 版本檢測結束");
		frame:SetScript("OnUpdate", nil);
	end
end

local function CheckVersion()
	raid = {};
	DEFAULT_CHAT_FRAME:AddMessage("RadenUnstableVita - 版本檢測中");
	SendAddonMessage("RUVcheck", "cv", "RAID");

	members = GetNumGroupMembers();
	local i=1;
	for i=1, members do
		name, _, subgroup, _, _, _, _, _, _, _, _ = GetRaidRosterInfo(i);
		if subgroup <= 5 then
			raid[name] = "未找到RUV或過舊的版本";
		end
	end
			
	checkVersionElapsed = 0.0;
	frame:SetScript("OnUpdate", CheckVersionResult);
end

local function CheckCircle(startPerson, checkType)
	raidCircle = {};
	raidCircleStartPerson = startPerson;
	raidCircleLastPerson = nil;
	raidCircleCount = 0;
	
	if startPerson ~= nil then
		if checkType == "circle" then
			SendAddonMessage("RUVcheckCircle", "target", "WHISPER", startPerson);
		elseif checkType == "test" then
			SendAddonMessage("RUVcheckCircle", "test", "WHISPER", startPerson);
		end
	end
end

local function SetTarget (str)
	local target, command;
	local ary = {};

	target, command = str:match ("(%S+)%s+(.*)");

	if UnitInRaid (target) == nil then
		DEFAULT_CHAT_FRAME:AddMessage (target .. "不是合法的目標");
		return;
	end

	local next, prev, color, coverage = "0", "0", "0", "0";
	local k, v;

	for k, v in command:gmatch ("(%S+)%s*=%s*(%S+)") do
		if k == "next" then
			next = v;
		elseif k == "prev" then
			prev = v;
		elseif k == "color" then
			color = v;
		elseif k == "coverage" then
			coverage = v;
		end
	end

	SendAddonMessage ("RUVsetTarget", "set " .. next .. " " .. prev .. " " .. color .. " " .. coverage, "WHISPER", target);
end

local function AutoSet ()
	local members = GetNumGroupMembers ();
	local name, subgroup;
	local groupIndex = {};
	local memberList = {};
	local i, j, memberN;

	memberN = 0;
	for i = 1, members do
		name, _, subgroup, _, _, _, _, _, _, _, _ = GetRaidRosterInfo(i);
		groupIndex[name] = subgroup;
		if subgroup >= 2 and subgroup <= 5 then
			memberList[memberN] = name;
			memberN = memberN + 1;
		end
	end
	
	local tmp;

	for i = 0, memberN - 2 do
		for j = 0, memberN - 2 - i do
			if groupIndex[ memberList[j] ] > groupIndex[ memberList[j+1] ] or groupIndex[ memberList[j] ] == groupIndex[ memberList[j+1] ] and memberList[j] > memberList[j+1] then
				tmp = memberList[j];
				memberList[j] = memberList[j+1];
				memberList[j+1] = tmp;
			end
		end
	end

	local c;
	if memberN >= 2 then
		SetTarget (memberList[0] .. " color=黃 next=" .. memberList[1] .. " prev=" .. memberList[memberN - 1]);
		for i = 1, memberN - 2 do
			if i % 2 == 0 then
				c = "黃";
			else
				c = "紫";
			end
			SetTarget (memberList[i] .. " next=" .. memberList[i+1] .. " prev=" .. memberList[i-1] .. " color=" .. c);
		end
		SetTarget (memberList[memberN-1] .. " color=紫 next=" .. memberList[0] .. " prev=" .. memberList[memberN-2]);
	elseif memberN == 1 then
		SetTarget (memberList[0] .. " color=黃 next=" .. memberList[0] .. " prev=" .. memberList[0]);
	end
end

local function prevTargetHasDebuff()
	local player = UnitName("player");

	if HasVitaSensitive ("player") then
		SendChatMessage (player .. "身上已有生命敏感，別出去！", "SAY");
	else

		if Color == nil or Color == "" then
			SendChatMessage("++"..player.."準備接電++" , "SAY")
		else
			SendChatMessage("++"..player.."去" .. Color .. "色準備接電++" , "SAY")
		end
		PlaySoundFile ("Interface\\Addons\\RadenUnstableVita\\sounds\\ex_mop_lkzc.mp3", "Master");
	end
end

local function SetCoverage (coverage) 
	if coverage == nil then
		DEFAULT_CHAT_FRAME:AddMessage ("Usage: /raden setcoverage ID");
		return ;
	end
	if UnitInRaid (coverage) == nil then
		DEFAULT_CHAT_FRAME:AddMessage (coverage .. " 不是合法的團隊成員");
		return ;
	end
	
	local i;
	local members = GetNumGroupMembers ();

	for i = 1, members do
		SetTarget (UnitName ("raid" .. i) .. " coverage=" .. coverage);
	end
end

local function ClearTarget ()
	local i;
	local members = GetNumGroupMembers ();
	for i = 1, members do
		SendAddonMessage ("RUVsetTarget", "clear", "WHISPER", UnitName ("raid" .. i));
	end
end

local function SetSequence (str)
	local i, n, ary = 0, 0, {};

	local s;
	
	for s in str:gmatch ("%S+") do
		if UnitInRaid (s) == nil then
			DEFAULT_CHAT_FRAME:AddMessage (s .. " 不是合法的團隊成員");
			return ;
		end

		ary[n] = s;
		n = n + 1;
	end
	ary[n] = ary[0];
	ary[-1] = ary[n - 1];

	local c;
	for i = 0, n - 1 do
		if i % 2 == 0 then
			c = "黃";
		else
			c = "紫";
		end
		SetTarget (ary[i] .. " next=" .. ary[i+1] .. " prev=" .. ary[i-1] .. " color=" .. c);
	end
end

function frame:OnEvent(ev, arg1, event, arg3, arg4, source, _, _, _, target, _, _, spellID, _, _, _, count)
--                            1    2       3     4    5     6  7  8    9    10 11    12    13 14 15   16
	
	if ev == "COMBAT_LOG_EVENT_UNFILTERED" then
	
		local player = UnitName("player")
		if player ~= target and PrevTarget ~= target then 
			return 
		end
		
		if test then
			if spellID ~= 6788 then  -- test with priest weakened soul
				return 
			end
		else
			if spellID ~= 138297 and spellID ~= 138308 then 
				return 
			end
		end
		
		if event == "SPELL_AURA_APPLIED" then
			if target == player then
				startCountdown()
			else  
				-- target == PrevTarget 
				prevTargetHasDebuff()
			end
		else
			return
		end
	elseif ev == "CHAT_MSG_ADDON" then
		if arg1 == "RUVcheck" then
			SendAddonMessage("RUVversion", version, "WHISPER", arg4);
		elseif arg1 == "RUVversion" then
			raid[arg4] = event;
		elseif arg1 == "RUVenableTest" then
			DEFAULT_CHAT_FRAME:AddMessage("TestMode on")
			frame:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
			test = true
		elseif arg1 == "RUVdisableTest" then
			DEFAULT_CHAT_FRAME:AddMessage("TestMode off")
			--to prevent bug, not unregister for now
			--frame:UnregisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
			test = false
		elseif arg1 == "RUVnext" then
			prevTargetHasDebuff();
		elseif arg1 == "RUVcheckCircle" then
			if event == "target" then
				SendAddonMessage("RUVcheckCircle", "response " .. NextTarget .. " " .. PrevTarget, "WHISPER", arg4);
			elseif event == "test" then
				raidCircleTester = arg4;
				SendAddonMessage("RUVnext", "next", "WHISPER", NextTarget);
				startCountdown();
			else
				local str;
				local attr = {};
				local i = 0;
				for str in event:gmatch("%S+") do
					attr[i] = str;
					i = i+1;
				end
				
				--DEFAULT_CHAT_FRAME:AddMessage("attr[0]: " .. attr[0] .. ", attr[1]: " .. attr[1] .. ", attr[2]: " .. attr[2]);
				--DEFAULT_CHAT_FRAME:AddMessage("raidCircleStartPerson: " .. raidCircleStartPerson);
				if attr[0] == "response" or attr[0] == "responseTest" then
					raidCircle[arg4] = attr[1];
					raidCircleCount = raidCircleCount + 1;
					
					if raidCircleLastPerson ~= nil and raidCircleLastPerson ~= attr[2] then
						DEFAULT_CHAT_FRAME:AddMessage(arg4 .. "的上一個人應為: " .. raidCircleLastPerson);
						SendChatMessage("你的上一個人是: " .. raidCircleLastPerson, "WHISPER", nil, arg4);
					end
					
					if attr[1] == raidCircleStartPerson then
						DEFAULT_CHAT_FRAME:AddMessage("People in circle: " .. raidCircleCount);
						
						local raidCheck = {};
						local start = raidCircleStartPerson;
						raidCheck[start] = true;
						DEFAULT_CHAT_FRAME:AddMessage(start);
						while raidCheck[raidCircle[start]] ~= true do
							start = raidCircle[start];
							raidCheck[start] = true;
							DEFAULT_CHAT_FRAME:AddMessage(" => " .. start);
						end
					elseif raidCircle[attr[1]] ~= nil and attr[1] ~= raidCircleStartPerson then
						DEFAULT_CHAT_FRAME:AddMessage("錯誤的迴圈!");
						
						local raidCheck = {};
						local start = raidCircleStartPerson;
						local circleString = "";
						raidCheck[start] = true;
						circleString = circleString .. start;
						while raidCheck[raidCircle[start]] ~= true do
							start = raidCircle[start];
							raidCheck[start] = true;
							circleString = circleString .. " => " .. start;
						end
						DEFAULT_CHAT_FRAME:AddMessage(circleString);
					else
						if attr[0] == "response" then
							SendAddonMessage("RUVcheckCircle", "target", "WHISPER", attr[1]);
						elseif attr[0] == "responseTest" then
							SendAddonMessage("RUVcheckCircle", "test", "WHISPER", attr[1]);
						end
					end
				end
			end
		elseif arg1 == "RUVsetTarget" then
			local attr = {"0", "0", "0", "0"};
			local str;
			local i = 0;
			for str in event:gmatch ("%S+") do
				attr[i] = str;
				i = i + 1;
			end
			
			if attr[0] == "set" then
				if attr[1] ~= "0" then
					NextTarget = attr[1];
					DEFAULT_CHAT_FRAME:AddMessage (arg4 .. "設置你的NextTarget為" .. NextTarget);
				end
				if attr[2] ~= "0" then
					PrevTarget = attr[2];
					DEFAULT_CHAT_FRAME:AddMessage (arg4 .. "設置你的PrevTarget為" .. PrevTarget);
				end
				if attr[3] ~= "0" then
					Color = attr[3];
					DEFAULT_CHAT_FRAME:AddMessage (arg4 .. "設置你的Color為" .. Color);
				end
				if attr[4] ~= "0" then
					Coverage = attr[4];
					DEFAULT_CHAT_FRAME:AddMessage (arg4 .. "設置你的Coverage為" .. Coverage);
				end
				SendAddonMessage ("RUVsetTarget","response", "WHISPER", arg4);
			elseif attr[0] == "clear" then
				NextTarget = "";
				PrevTarget = "";
				Color = nil;
				Coverage = nil;
				DEFAULT_CHAT_FRAME:AddMessage (arg4 .. "清空了你的NextTarget/PrevTarget/Color/Coverage");
				SendAddonMessage ("RUVsetTarget","response", "WHISPER", arg4);
			else -- attr[0] = "response"
				DEFAULT_CHAT_FRAME:AddMessage (arg4 .. "已被成功設置");
				isSettingTarget = false;
			end
		end
	else
		-- ZONE_CHANGED / ZONE_CHANGED_INDOORS / ZONE_CHANGED_NEW_AREA
		update_tracking()
	end
end

frame:RegisterEvent("ZONE_CHANGED")
frame:RegisterEvent("ZONE_CHANGED_INDOORS")
frame:RegisterEvent("ZONE_CHANGED_NEW_AREA")
frame:RegisterEvent("CHAT_MSG_ADDON");

RegisterAddonMessagePrefix("RUVcheck");
RegisterAddonMessagePrefix("RUVversion");
RegisterAddonMessagePrefix("RUVenableTest");
RegisterAddonMessagePrefix("RUVdisableTest");
RegisterAddonMessagePrefix("RUVcheckCircle");
RegisterAddonMessagePrefix("RUVnext");
RegisterAddonMessagePrefix("RUVsetTarget");

update_tracking()

frame:SetScript("OnEvent", frame.OnEvent)


-- SLASH COMMAND --

SLASH_RADENUNSTABLEVITA1 = "/raden"
SlashCmdList["RADENUNSTABLEVITA"] = function(msg)
 
	local ary = {}
	local i = 0
	for v in msg:gmatch("%S+") do
		ary[i] = v		
		--DEFAULT_CHAT_FRAME:AddMessage(ary[i])
		i = i+1
	end
	
	if i == 0 then
		DEFAULT_CHAT_FRAME:AddMessage ("RadenUnstableVita - type /raden help for more information.");
		return
	end
	
	local cmd = ary[0]:lower()
	local cmd2 = nil;
	if ary[1] ~= nil then
			cmd2 = ary[1]:lower();
	end

	if cmd == "say" then
    		startCountdown();
	elseif cmd == "help" then
		DEFAULT_CHAT_FRAME:AddMessage ("Available commands for RadenUnstableVita:");
		DEFAULT_CHAT_FRAME:AddMessage ("/raden (say | target | cleartarget | count)");
		DEFAULT_CHAT_FRAME:AddMessage ("/raden (prev | next | color | coverage)");
		DEFAULT_CHAT_FRAME:AddMessage ("/raden test (enable | disable)");
		DEFAULT_CHAT_FRAME:AddMessage ("/raden check (version | circle ID | test ID)");
		DEFAULT_CHAT_FRAME:AddMessage ("/raden set target ID command1 [command2 ..]");
		DEFAULT_CHAT_FRAME:AddMessage ("/raden set sequeunce ID1 [ID2 ..]");
		DEFAULT_CHAT_FRAME:AddMessage ("/raden set (auto | coverage ID | cleartarget)");		
	elseif cmd == "cleartarget" then
		PrevTarget = ""
		NextTarget = ""
		Color = nil;
		Coverage = nil;
		DEFAULT_CHAT_FRAME:AddMessage("PrevTarget/NextTarget/Color/Coverage cleared")
	elseif cmd == "target" then
		if PrevTarget ~= nil and PrevTarget ~= "" then
			DEFAULT_CHAT_FRAME:AddMessage("PrevTarget: " .. PrevTarget)
		else
			DEFAULT_CHAT_FRAME:AddMessage("PrevTarget not set")
		end
		if NextTarget ~= nil and NextTarget ~= "" then
			DEFAULT_CHAT_FRAME:AddMessage("NextTarget: " .. NextTarget)
		else 
			DEFAULT_CHAT_FRAME:AddMessage("NextTarget not set")
		end
		if Color ~= nil and Color ~= "" then
			DEFAULT_CHAT_FRAME:AddMessage ("站位光柱:" .. Color);
		else
			DEFAULT_CHAT_FRAME:AddMessage ("站位光柱未指定");
		end
		if Coverage ~= nil and Coverage ~= "" then
			DEFAULT_CHAT_FRAME:AddMessage ("補位人員:" .. Coverage);
		else
			DEFAULT_CHAT_FRAME:AddMessage ("補位人員未指定");
		end
	elseif cmd == "prev" then
	    	if ary[1] ~= nil and ary[1] ~= "" then
    			PrevTarget = ary[1]
			DEFAULT_CHAT_FRAME:AddMessage("PrevTarget: " .. PrevTarget)
	    	else
    			DEFAULT_CHAT_FRAME:AddMessage("Usage: /raden prev PrevTarget")
	    	end
	elseif cmd == "next" then
    		if ary[1] ~= nil and ary[1] ~= "" then
    			NextTarget = ary[1]
			DEFAULT_CHAT_FRAME:AddMessage("NextTarget: " .. NextTarget)
	    	else
    			DEFAULT_CHAT_FRAME:AddMessage("Usage: /raden next NextTarget")
	    	end
	elseif cmd == "color" then
		if ary[1] ~= nil and ary[1] ~= "" then
			Color = ary[1];
		end
		if Color == nil or Color == "" then
			DEFAULT_CHAT_FRAME:AddMessage ("站位光柱未指定，指令：/raden color 黃/紫");
		else
			DEFAULT_CHAT_FRAME:AddMessage ("站位光柱: " .. Color);
		end
	elseif cmd == "coverage" then
		if ary[1] ~= nil and ary[1] ~= "" then
			Coverage = ary[1];
		end
		if Coverage == nil or Coverage == "" then
			DEFAULT_CHAT_FRAME:AddMessage ("補位成員未指定，指令：/raden coverage ID");
		else
			DEFAULT_CHAT_FRAME:AddMessage ("補位成員: " .. Coverage);
		end
	elseif cmd == "count" then
	    	if ary[1] ~= nil and ary[1] ~= "" then
    			countdown = ary[1]
			DEFAULT_CHAT_FRAME:AddMessage("Count: " .. countdown)
	    	else
    			DEFAULT_CHAT_FRAME:AddMessage("Usage: /raden count countdown")
			DEFAULT_CHAT_FRAME:AddMessage("Current Count: " .. countdown)
	    	end
	elseif cmd == "test" then
		if IsInRaid() then
			if UnitIsGroupAssistant("player") or UnitIsGroupLeader("player") then
				if cmd2 == "enable" then
					DEFAULT_CHAT_FRAME:AddMessage("RadenUnstableVita - 啟動團隊測試");
					SendAddonMessage("RUVenableTest", "test", "RAID");
				elseif cmd2 == "disable" then
					DEFAULT_CHAT_FRAME:AddMessage("RadenUnstableVita - 關閉團隊測試");
					SendAddonMessage("RUVdisableTest", "test", "RAID");
				end
			else
				DEFAULT_CHAT_FRAME:AddMessage("RadenUnstableVita - 測試模式只有隊長或助手可以用!");
			end
		else
			DEFAULT_CHAT_FRAME:AddMessage("RadenUnstableVita - 不在團隊中!");
		end
	elseif cmd == "check" then
		if IsInRaid() then
			if UnitIsGroupAssistant("player") or UnitIsGroupLeader("player") then
				if cmd2 == "version" then
					CheckVersion();
				elseif cmd2 == "circle" or cmd2 == "test" then
					CheckCircle(ary[2], cmd2);
				end
			else
				DEFAULT_CHAT_FRAME:AddMessage("RadenUnstableVita - 檢測模式只有隊長或助手可以用!");
			end
		else
			DEFAULT_CHAT_FRAME:AddMessage("RadenUnstableVita - 不在團隊中!");
		end
	elseif cmd == "set" then
		if IsInRaid() then
			if UnitIsGroupAssistant("player") or UnitIsGroupLeader("player") then
				if cmd2 == "target" then
					if i >= 3 then
						local str = msg:match ("%S+%s+%S+%s+(.*)");
						SetTarget (str);
					else
						DEFAULT_CHAT_FRAME:AddMessage("Usage: /raden set target ID command1 [command2 ..]");
						DEFAULT_CHAT_FRAME:AddMessage ("Possible Commands: next=ID, prev=ID, color=黃/紫, coverage=ID");
					end
				elseif cmd2 == "auto" then
					if GetRaidDifficultyID() % 2 == 0 then
						AutoSet ();
					else
						DEFAULT_CHAT_FRAME:AddMessage("RadenUnstableVita - 自動設定功能僅能用在25人團隊");
					end
				elseif cmd2 == "coverage" then
					SetCoverage (ary[2]);
				elseif cmd2 == "sequence" then
					if i >= 3 then
						local str = msg:match ("%S+%s+%S+%s+(.*)");
						SetSequence (str);
					else
						DEFAULT_CHAT_FRAME:AddMessage ("Usage: /raden set sequence ID1 [ID2 ...]");
					end
				elseif cmd2 == "cleartarget" then
					ClearTarget ();
				else
					DEFAULT_CHAT_FRAME:AddMessage ("Usage: /raden set (target | auto | coverage | sequence)");
				end
			else
				DEFAULT_CHAT_FRAME:AddMessage("RadenUnstableVita - 設定功能只有隊長或助手可以用!");
			end
		else
			DEFAULT_CHAT_FRAME:AddMessage("RadenUnstableVita - 不在團隊中!");
		end
	else
		DEFAULT_CHAT_FRAME:AddMessage ("Unknown RUA command, type /raden help for more information.");
	end
end